<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>浅谈消息队列及常见的消息中间件 | JavaKeeper</title>
    <meta name="generator" content="VuePress 1.5.4">
    <link rel="icon" href="/icon.svg">
    <script>
        var _hmt = _hmt || [];
        (function() {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?a949a9b30eb86ac0159e735ff8670c03";
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(hm, s);
            // 引入谷歌,不需要可删除这段
            var hm1 = document.createElement("script");
            hm1.src = "https://www.googletagmanager.com/gtag/js?id=UA-169923503-1";
            var s1 = document.getElementsByTagName("script")[0]; 
            s1.parentNode.insertBefore(hm1, s1);
        })();
        // 谷歌加载,不需要可删除
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'UA-169923503-1');
    </script>
    <meta name="description" content="">
    <meta name="keywords" content="JavaKeeper,Java,Java开发,算法,blog">
    <link rel="preload" href="/assets/css/0.styles.91f57736.css" as="style"><link rel="preload" href="/assets/js/app.447d4224.js" as="script"><link rel="preload" href="/assets/js/3.9d76740c.js" as="script"><link rel="preload" href="/assets/js/1.c4fd7d2e.js" as="script"><link rel="preload" href="/assets/js/7.6609d4d6.js" as="script"><link rel="prefetch" href="/assets/js/10.8cf3be2c.js"><link rel="prefetch" href="/assets/js/100.74f35ab8.js"><link rel="prefetch" href="/assets/js/101.7a062346.js"><link rel="prefetch" href="/assets/js/102.c9485235.js"><link rel="prefetch" href="/assets/js/103.d88a3805.js"><link rel="prefetch" href="/assets/js/104.6e034144.js"><link rel="prefetch" href="/assets/js/105.d22f7450.js"><link rel="prefetch" href="/assets/js/106.a6cb54b0.js"><link rel="prefetch" href="/assets/js/107.7b65e72b.js"><link rel="prefetch" href="/assets/js/108.eb5804bb.js"><link rel="prefetch" href="/assets/js/109.05f775e5.js"><link rel="prefetch" href="/assets/js/11.c54ae13c.js"><link rel="prefetch" href="/assets/js/110.51d3d641.js"><link rel="prefetch" href="/assets/js/111.022b64a7.js"><link rel="prefetch" href="/assets/js/112.da8afd52.js"><link rel="prefetch" href="/assets/js/113.05a17b18.js"><link rel="prefetch" href="/assets/js/114.8960d913.js"><link rel="prefetch" href="/assets/js/115.67919f68.js"><link rel="prefetch" href="/assets/js/116.62b0cd71.js"><link rel="prefetch" href="/assets/js/117.ebac3eff.js"><link rel="prefetch" href="/assets/js/118.ecd629bd.js"><link rel="prefetch" href="/assets/js/119.a09a0897.js"><link rel="prefetch" href="/assets/js/12.60aa3b24.js"><link rel="prefetch" href="/assets/js/120.bf639d3d.js"><link rel="prefetch" href="/assets/js/121.b89d0c8e.js"><link rel="prefetch" href="/assets/js/122.1a75ff83.js"><link rel="prefetch" href="/assets/js/123.d2127132.js"><link rel="prefetch" href="/assets/js/124.2caff9e0.js"><link rel="prefetch" href="/assets/js/125.9b9f966a.js"><link rel="prefetch" href="/assets/js/126.58cdfb3d.js"><link rel="prefetch" href="/assets/js/127.8ef09c53.js"><link rel="prefetch" href="/assets/js/128.efdc2ae4.js"><link rel="prefetch" href="/assets/js/129.e35cbc57.js"><link rel="prefetch" href="/assets/js/13.125c13a0.js"><link rel="prefetch" href="/assets/js/130.f01a55e3.js"><link rel="prefetch" href="/assets/js/131.65205f4a.js"><link rel="prefetch" href="/assets/js/132.f42c5a0a.js"><link rel="prefetch" href="/assets/js/133.9ba468b3.js"><link rel="prefetch" href="/assets/js/134.7b597ba9.js"><link rel="prefetch" href="/assets/js/135.fb828b9a.js"><link rel="prefetch" href="/assets/js/136.3887532f.js"><link rel="prefetch" href="/assets/js/137.549bae01.js"><link rel="prefetch" href="/assets/js/138.db8d423d.js"><link rel="prefetch" href="/assets/js/139.dbaf2267.js"><link rel="prefetch" href="/assets/js/14.bd1d0b0d.js"><link rel="prefetch" href="/assets/js/140.6cb65fdc.js"><link rel="prefetch" href="/assets/js/141.9bd6cc4b.js"><link rel="prefetch" href="/assets/js/142.552db5ed.js"><link rel="prefetch" href="/assets/js/143.2c9f2bf4.js"><link rel="prefetch" href="/assets/js/144.fba98a15.js"><link rel="prefetch" href="/assets/js/145.c42f3a21.js"><link rel="prefetch" href="/assets/js/146.596d4d33.js"><link rel="prefetch" href="/assets/js/147.c48ae5c1.js"><link rel="prefetch" href="/assets/js/148.71064871.js"><link rel="prefetch" href="/assets/js/149.16582d21.js"><link rel="prefetch" href="/assets/js/15.f247873b.js"><link rel="prefetch" href="/assets/js/150.ead09aca.js"><link rel="prefetch" href="/assets/js/151.971fdf4b.js"><link rel="prefetch" href="/assets/js/152.369c9362.js"><link rel="prefetch" href="/assets/js/153.371edd15.js"><link rel="prefetch" href="/assets/js/154.e090b491.js"><link rel="prefetch" href="/assets/js/155.c68bf602.js"><link rel="prefetch" href="/assets/js/156.304aea8d.js"><link rel="prefetch" href="/assets/js/157.83beef7f.js"><link rel="prefetch" href="/assets/js/158.bb1794b0.js"><link rel="prefetch" href="/assets/js/159.2d54e792.js"><link rel="prefetch" href="/assets/js/16.04336c71.js"><link rel="prefetch" href="/assets/js/160.99d56586.js"><link rel="prefetch" href="/assets/js/161.edf660aa.js"><link rel="prefetch" href="/assets/js/162.0b84606e.js"><link rel="prefetch" href="/assets/js/163.b59e0d60.js"><link rel="prefetch" href="/assets/js/164.d9eb8228.js"><link rel="prefetch" href="/assets/js/165.ca624c79.js"><link rel="prefetch" href="/assets/js/166.025b2ba1.js"><link rel="prefetch" href="/assets/js/167.abc982cc.js"><link rel="prefetch" href="/assets/js/168.27ca13dc.js"><link rel="prefetch" href="/assets/js/169.41e753a2.js"><link rel="prefetch" href="/assets/js/17.43b3c1c8.js"><link rel="prefetch" href="/assets/js/170.626319e1.js"><link rel="prefetch" href="/assets/js/171.a221dddf.js"><link rel="prefetch" href="/assets/js/172.464b2361.js"><link rel="prefetch" href="/assets/js/173.96a3afee.js"><link rel="prefetch" href="/assets/js/174.116607c2.js"><link rel="prefetch" href="/assets/js/175.ea3e8659.js"><link rel="prefetch" href="/assets/js/176.7d7b8afc.js"><link rel="prefetch" href="/assets/js/177.a6e00aa0.js"><link rel="prefetch" href="/assets/js/178.1f93afaf.js"><link rel="prefetch" href="/assets/js/179.3aa00dcd.js"><link rel="prefetch" href="/assets/js/18.d81b44d5.js"><link rel="prefetch" href="/assets/js/180.f8b2b75a.js"><link rel="prefetch" href="/assets/js/181.8e11258a.js"><link rel="prefetch" href="/assets/js/182.22243941.js"><link rel="prefetch" href="/assets/js/183.d051fdf6.js"><link rel="prefetch" href="/assets/js/184.a994075e.js"><link rel="prefetch" href="/assets/js/185.776c7e16.js"><link rel="prefetch" href="/assets/js/186.f1887955.js"><link rel="prefetch" href="/assets/js/187.da0d3626.js"><link rel="prefetch" href="/assets/js/188.8dfc358f.js"><link rel="prefetch" href="/assets/js/189.dcac5a59.js"><link rel="prefetch" href="/assets/js/19.1b3d66e1.js"><link rel="prefetch" href="/assets/js/190.c7e413d0.js"><link rel="prefetch" href="/assets/js/191.d9806121.js"><link rel="prefetch" href="/assets/js/192.869791da.js"><link rel="prefetch" href="/assets/js/193.2d74c4c8.js"><link rel="prefetch" href="/assets/js/194.c73a1909.js"><link rel="prefetch" href="/assets/js/195.e8c74834.js"><link rel="prefetch" href="/assets/js/20.bd5949ec.js"><link rel="prefetch" href="/assets/js/21.3fcf98cf.js"><link rel="prefetch" href="/assets/js/22.2fa1e2e8.js"><link rel="prefetch" href="/assets/js/23.1ae64bb4.js"><link rel="prefetch" href="/assets/js/24.7bdf7387.js"><link rel="prefetch" href="/assets/js/25.392c436e.js"><link rel="prefetch" href="/assets/js/26.58acbd4b.js"><link rel="prefetch" href="/assets/js/27.c725bdd5.js"><link rel="prefetch" href="/assets/js/28.6c9bda1e.js"><link rel="prefetch" href="/assets/js/29.e656b537.js"><link rel="prefetch" href="/assets/js/30.2c326fc7.js"><link rel="prefetch" href="/assets/js/31.e6c9fa30.js"><link rel="prefetch" href="/assets/js/32.c9c88437.js"><link rel="prefetch" href="/assets/js/33.0c53373c.js"><link rel="prefetch" href="/assets/js/34.9821e543.js"><link rel="prefetch" href="/assets/js/35.de8253eb.js"><link rel="prefetch" href="/assets/js/36.d182f929.js"><link rel="prefetch" href="/assets/js/37.9fa79014.js"><link rel="prefetch" href="/assets/js/38.9bebff76.js"><link rel="prefetch" href="/assets/js/39.19a3a2d4.js"><link rel="prefetch" href="/assets/js/4.564edb9d.js"><link rel="prefetch" href="/assets/js/40.cca6955f.js"><link rel="prefetch" href="/assets/js/41.854cd09a.js"><link rel="prefetch" href="/assets/js/42.ca7b612f.js"><link rel="prefetch" href="/assets/js/43.87027d58.js"><link rel="prefetch" href="/assets/js/44.8c2b4f4b.js"><link rel="prefetch" href="/assets/js/45.dffb4e08.js"><link rel="prefetch" href="/assets/js/46.f58049a5.js"><link rel="prefetch" href="/assets/js/47.6854070c.js"><link rel="prefetch" href="/assets/js/48.6cd9fa3d.js"><link rel="prefetch" href="/assets/js/49.e8861afa.js"><link rel="prefetch" href="/assets/js/5.5c31d62f.js"><link rel="prefetch" href="/assets/js/50.703bffab.js"><link rel="prefetch" href="/assets/js/51.6655c373.js"><link rel="prefetch" href="/assets/js/52.deb2eb09.js"><link rel="prefetch" href="/assets/js/53.6e0ed77d.js"><link rel="prefetch" href="/assets/js/54.b05c58ad.js"><link rel="prefetch" href="/assets/js/55.49c8164e.js"><link rel="prefetch" href="/assets/js/56.a5574e6b.js"><link rel="prefetch" href="/assets/js/57.58cb0de4.js"><link rel="prefetch" href="/assets/js/58.52345112.js"><link rel="prefetch" href="/assets/js/59.663ce78d.js"><link rel="prefetch" href="/assets/js/6.a9df34ee.js"><link rel="prefetch" href="/assets/js/60.f06adde2.js"><link rel="prefetch" href="/assets/js/61.170255a1.js"><link rel="prefetch" href="/assets/js/62.9d120050.js"><link rel="prefetch" href="/assets/js/63.70cced6b.js"><link rel="prefetch" href="/assets/js/64.577f3548.js"><link rel="prefetch" href="/assets/js/65.c037b29d.js"><link rel="prefetch" href="/assets/js/66.7dd1045f.js"><link rel="prefetch" href="/assets/js/67.d3aa4d6c.js"><link rel="prefetch" href="/assets/js/68.526dbb61.js"><link rel="prefetch" href="/assets/js/69.58269266.js"><link rel="prefetch" href="/assets/js/70.64108f1b.js"><link rel="prefetch" href="/assets/js/71.1e95e0a6.js"><link rel="prefetch" href="/assets/js/72.42e7ec94.js"><link rel="prefetch" href="/assets/js/73.dad4e1c5.js"><link rel="prefetch" href="/assets/js/74.28ea286a.js"><link rel="prefetch" href="/assets/js/75.dd6d4c6f.js"><link rel="prefetch" href="/assets/js/76.ca6539df.js"><link rel="prefetch" href="/assets/js/77.feb13b0e.js"><link rel="prefetch" href="/assets/js/78.321e90e6.js"><link rel="prefetch" href="/assets/js/79.68eb8fcf.js"><link rel="prefetch" href="/assets/js/8.396d51fd.js"><link rel="prefetch" href="/assets/js/80.4edb5321.js"><link rel="prefetch" href="/assets/js/81.735d7e57.js"><link rel="prefetch" href="/assets/js/82.fa120bdf.js"><link rel="prefetch" href="/assets/js/83.bf755f94.js"><link rel="prefetch" href="/assets/js/84.9b32070c.js"><link rel="prefetch" href="/assets/js/85.592aca7c.js"><link rel="prefetch" href="/assets/js/86.4dcd9e73.js"><link rel="prefetch" href="/assets/js/87.a9e546aa.js"><link rel="prefetch" href="/assets/js/88.2a423212.js"><link rel="prefetch" href="/assets/js/89.5f455115.js"><link rel="prefetch" href="/assets/js/9.adb074c6.js"><link rel="prefetch" href="/assets/js/90.5202da0a.js"><link rel="prefetch" href="/assets/js/91.02cee99d.js"><link rel="prefetch" href="/assets/js/92.f16bad0b.js"><link rel="prefetch" href="/assets/js/93.f933634f.js"><link rel="prefetch" href="/assets/js/94.8e7b1d65.js"><link rel="prefetch" href="/assets/js/95.ee0e4a0a.js"><link rel="prefetch" href="/assets/js/96.e21d78c2.js"><link rel="prefetch" href="/assets/js/97.c87e514e.js"><link rel="prefetch" href="/assets/js/98.d123ac92.js"><link rel="prefetch" href="/assets/js/99.92d1b416.js">
    <link rel="stylesheet" href="/assets/css/0.styles.91f57736.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container no-sidebar" data-v-3ba18f14><div data-v-3ba18f14><div id="loader-wrapper" class="loading-wrapper" data-v-041fef5b data-v-3ba18f14 data-v-3ba18f14><div class="loader-main" data-v-041fef5b><div data-v-041fef5b></div><div data-v-041fef5b></div><div data-v-041fef5b></div><div data-v-041fef5b></div></div> <!----> <!----></div> <div class="password-shadow password-wrapper-out" style="display:none;" data-v-68139a52 data-v-3ba18f14 data-v-3ba18f14><h3 class="title" style="display:none;" data-v-68139a52 data-v-68139a52>JavaKeeper</h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-68139a52 data-v-68139a52><input type="password" value="" data-v-68139a52> <span data-v-68139a52>Konck! Knock!</span> <button data-v-68139a52>OK</button></label> <div class="footer" style="display:none;" data-v-68139a52 data-v-68139a52><span data-v-68139a52><i class="iconfont reco-theme" data-v-68139a52></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-68139a52>vuePress-theme-reco</a></span> <span data-v-68139a52><i class="iconfont reco-copyright" data-v-68139a52></i> <a data-v-68139a52><span data-v-68139a52>海星</span>
            
          <!---->
          2020
        </a></span></div></div> <div class="hide" data-v-3ba18f14><header class="navbar" data-v-3ba18f14><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">JavaKeeper</span></a> <div class="links"><div class="color-picker"><a class="color-button"><i class="iconfont reco-color"></i></a> <div class="color-picker-menu" style="display:none;"><div class="mode-options"><h4 class="title">Choose mode</h4> <ul class="color-mode-options"><li class="dark">dark</li><li class="auto active">auto</li><li class="light">light</li></ul></div></div></div> <div class="search-box"><i class="iconfont reco-search"></i> <input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/java/" class="nav-link"><i class="iconfont undefined"></i>
  Java
</a></div><div class="nav-item"><a href="/data-structure-algorithms/" class="nav-link"><i class="iconfont undefined"></i>
  数据结构与算法
</a></div><div class="nav-item"><a href="/data-store/" class="nav-link"><i class="iconfont undefined"></i>
  数据存储与缓存
</a></div><div class="nav-item"><a href="/interview/" class="nav-link"><i class="iconfont undefined"></i>
  直击面试
</a></div> <a href="https://github.com/Jstarfish/JavaKeeper" target="_blank" rel="noopener noreferrer" class="repo-link"><i class="iconfont reco-github"></i>
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask" data-v-3ba18f14></div> <aside class="sidebar" data-v-3ba18f14><div class="personal-info-wrapper" data-v-5f6acefd data-v-3ba18f14><!----> <h3 class="name" data-v-5f6acefd>
    海星
  </h3> <div class="num" data-v-5f6acefd><div data-v-5f6acefd><h3 data-v-5f6acefd>0</h3> <h6 data-v-5f6acefd>Article</h6></div> <div data-v-5f6acefd><h3 data-v-5f6acefd>0</h3> <h6 data-v-5f6acefd>Tag</h6></div></div> <hr data-v-5f6acefd></div> <nav class="nav-links"><div class="nav-item"><a href="/java/" class="nav-link"><i class="iconfont undefined"></i>
  Java
</a></div><div class="nav-item"><a href="/data-structure-algorithms/" class="nav-link"><i class="iconfont undefined"></i>
  数据结构与算法
</a></div><div class="nav-item"><a href="/data-store/" class="nav-link"><i class="iconfont undefined"></i>
  数据存储与缓存
</a></div><div class="nav-item"><a href="/interview/" class="nav-link"><i class="iconfont undefined"></i>
  直击面试
</a></div> <a href="https://github.com/Jstarfish/JavaKeeper" target="_blank" rel="noopener noreferrer" class="repo-link"><i class="iconfont reco-github"></i>
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav> <!----> </aside> <div class="password-shadow password-wrapper-in" style="display:none;" data-v-68139a52 data-v-3ba18f14><h3 class="title" style="display:none;" data-v-68139a52 data-v-68139a52></h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-68139a52 data-v-68139a52><input type="password" value="" data-v-68139a52> <span data-v-68139a52>Konck! Knock!</span> <button data-v-68139a52>OK</button></label> <div class="footer" style="display:none;" data-v-68139a52 data-v-68139a52><span data-v-68139a52><i class="iconfont reco-theme" data-v-68139a52></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-68139a52>vuePress-theme-reco</a></span> <span data-v-68139a52><i class="iconfont reco-copyright" data-v-68139a52></i> <a data-v-68139a52><span data-v-68139a52>海星</span>
            
          <!---->
          2020
        </a></span></div></div> <div data-v-3ba18f14><main class="page"><div class="page-title" style="display:none;"><h1 class="title">浅谈消息队列及常见的消息中间件</h1> <div data-v-5d8dbdb4><i class="iconfont reco-account" data-v-5d8dbdb4><span data-v-5d8dbdb4>海星</span></i> <!----> <!----> <!----></div></div> <div class="theme-reco-content content__default" style="display:none;"><h1 id="浅谈消息队列及常见的消息中间件"><a href="#浅谈消息队列及常见的消息中间件" class="header-anchor">#</a> 浅谈消息队列及常见的消息中间件</h1> <blockquote></blockquote> <h2 id="前言"><a href="#前言" class="header-anchor">#</a> 前言</h2> <p><strong>消息队列</strong> 已经逐渐成为企业应用系统 <strong>内部通信</strong> 的核心手段。它具有 <strong>低耦合</strong>、<strong>可靠投递</strong>、<strong>广播</strong>、<strong>流量控制</strong>、<strong>最终一致性</strong> 等一系列功能。</p> <p>当前使用较多的 <strong>消息队列</strong> 有 <code>RabbitMQ</code>、<code>RocketMQ</code>、<code>ActiveMQ</code>、<code>Kafka</code>、<code>ZeroMQ</code>、<code>MetaMQ</code> 等，而部分<strong>数据库</strong> 如 <code>Redis</code>、<code>MySQL</code> 以及 <code>phxsql</code> 也可实现消息队列的功能。</p> <p><img src="/assets/img/mesage-what.3c989ab2.png" alt="img"></p> <h2 id="_1-消息队列概述"><a href="#_1-消息队列概述" class="header-anchor">#</a> 1. 消息队列概述</h2> <p><strong>消息队列</strong> 是指利用 <strong>高效可靠</strong> 的 <strong>消息传递机制</strong> 进行与平台无关的 <strong>数据交流</strong>，并基于<strong>数据通信</strong>来进行分布式系统的集成。</p> <p><img src="/assets/img/message-overview.7c0e4ce5.png" alt="img"></p> <p>通过提供 <strong>消息传递</strong> 和 <strong>消息排队</strong> 模型，它可以在 <strong>分布式环境</strong> 下提供 <strong>应用解耦</strong>、<strong>弹性伸缩</strong>、<strong>冗余存储</strong>、<strong>流量削峰</strong>、<strong>异步通信</strong>、<strong>数据同步</strong> 等等功能，其作为 <strong>分布式系统架构</strong> 中的一个重要组件，有着举足轻重的地位。</p> <h2 id="_2-消息队列的特点"><a href="#_2-消息队列的特点" class="header-anchor">#</a> 2. 消息队列的特点</h2> <h3 id="_2-1-采用异步处理模式"><a href="#_2-1-采用异步处理模式" class="header-anchor">#</a> 2.1. 采用异步处理模式</h3> <p><strong>消息发送者</strong> 可以发送一个消息而无须等待响应。<strong>消息发送者</strong> 将消息发送到一条 <strong>虚拟的通道</strong>（<strong>主题</strong> 或 <strong>队列</strong>）上，<strong>消息接收者</strong> 则 <strong>订阅</strong> 或是 <strong>监听</strong> 该通道。一条信息可能最终转发给 <strong>一个或多个</strong> 消息接收者，这些接收者都无需对 <strong>消息发送者</strong> 做出 <strong>同步回应</strong>。整个过程都是 <strong>异步的</strong>。</p> <h3 id="_2-2-应用系统之间解耦合"><a href="#_2-2-应用系统之间解耦合" class="header-anchor">#</a> 2.2. 应用系统之间解耦合</h3> <p>主要体现在如下两点：</p> <ol><li>发送者和接受者不必了解对方、只需要 <strong>确认消息</strong>；</li> <li>发送者和接受者 <strong>不必同时在线</strong>。</li></ol> <p>比如在线交易系统为了保证数据的 <strong>最终一致</strong>，在 <strong>支付系统</strong> 处理完成后会把 <strong>支付结果</strong> 放到 <strong>消息中间件</strong> 里，通知 <strong>订单系统</strong> 修改 <strong>订单支付状态</strong>。两个系统是通过消息中间件解耦的。</p> <h2 id="_3-消息队列的传递服务模型"><a href="#_3-消息队列的传递服务模型" class="header-anchor">#</a> 3. 消息队列的传递服务模型</h2> <p>消息队列的 <strong>传递服务模型</strong> 如下图所示：</p> <p><img src="/assets/img/message-server-mode.9a3079f0.png" alt="img"></p> <h2 id="_4-消息队列的的传输模式"><a href="#_4-消息队列的的传输模式" class="header-anchor">#</a> 4. 消息队列的的传输模式</h2> <h3 id="_4-1-点对点模型"><a href="#_4-1-点对点模型" class="header-anchor">#</a> 4.1. 点对点模型</h3> <p><strong>点对点模型</strong> 用于 <strong>消息生产者</strong> 和 <strong>消息消费者</strong> 之间 <strong>点到点</strong> 的通信。消息生产者将消息发送到由某个名字标识的特定消费者。这个名字实际上对应消费服务中的一个 <strong>队列</strong>（<code>Queue</code>），在消息传递给消费者之前它被 <strong>存储</strong> 在这个队列中。<strong>队列消息</strong> 可以放在 <strong>内存</strong> 中也可以 <strong>持久化</strong>，以保证在消息服务出现故障时仍然能够传递消息。</p> <p>传统的点对点消息中间件通常由 <strong>消息队列服务</strong>、<strong>消息传递服务</strong>、<strong>消息队列</strong> 和 <strong>消息应用程序接口</strong> <code>API</code> 组成，其典型的结构如下图所示。</p> <p><img src="/assets/img/message-queue.622034c3.png" alt="img"></p> <p><strong>特点：</strong></p> <ol><li>每个消息只用一个消费者；</li> <li>发送者和接受者没有时间依赖；</li> <li>接受者确认消息接受和处理成功。</li></ol> <p><strong>示意图如下所示：</strong></p> <p><img src="" alt="img"></p> <h3 id="_4-2-发布-订阅模型-pub-sub"><a href="#_4-2-发布-订阅模型-pub-sub" class="header-anchor">#</a> 4.2. 发布/订阅模型（Pub/Sub）</h3> <p><strong>发布者/订阅者</strong> 模型支持向一个特定的 <strong>消息主题</strong> 生产消息。<code>0</code> 或 <strong>多个订阅者</strong> 可能对接收来自 <strong>特定消息主题</strong> 的消息感兴趣。</p> <p>在这种模型下，发布者和订阅者彼此不知道对方，就好比是匿名公告板。这种模式被概况为：多个消费者可以获得消息，在 <strong>发布者</strong> 和 <strong>订阅者</strong> 之间存在 <strong>时间依赖性</strong>。发布者需要建立一个 <strong>订阅</strong>（<code>subscription</code>），以便能够消费者订阅。<strong>订阅者</strong> 必须保持 <strong>持续的活动状态</strong> 并 <strong>接收消息</strong>。</p> <p>在这种情况下，在订阅者 <strong>未连接时</strong>，发布的消息将在订阅者 <strong>重新连接</strong> 时 <strong>重新发布</strong>，如下图所示：</p> <p><img src="/assets/img/message-pubsub-mode.97d50643.png" alt="img"></p> <p><strong>特性：</strong></p> <ol><li>每个消息可以有多个订阅者；</li> <li>客户端只有订阅后才能接收到消息；</li> <li>持久订阅和非持久订阅。</li></ol> <blockquote><p>注意：</p> <ol><li>发布者和订阅者有时间依赖：接受者和发布者只有建立订阅关系才能收到消息；</li> <li>持久订阅：订阅关系建立后，消息就不会消失，不管订阅者是否都在线；</li> <li>非持久订阅：订阅者为了接受消息，必须一直在线。 当只有一个订阅者时约等于点对点模式</li></ol></blockquote> <h2 id="_5-消息队列应用场景"><a href="#_5-消息队列应用场景" class="header-anchor">#</a> 5. 消息队列应用场景</h2> <p>当你需要使用 <strong>消息队列</strong> 时，首先需要考虑它的必要性。可以使用消息队列的场景有很多，最常用的几种，是做 <strong>应用程序松耦合</strong>、<strong>异步处理模式</strong>、<strong>发布与订阅</strong>、<strong>最终一致性</strong>、<strong>错峰流控</strong> 和 <strong>日志缓冲</strong> 等。反之，如果需要 <strong>强一致性</strong>，关注业务逻辑的处理结果，则使用 <code>RPC</code> 显得更为合适。</p> <h3 id="_5-1-异步处理"><a href="#_5-1-异步处理" class="header-anchor">#</a> 5.1. 异步处理</h3> <p><strong>非核心</strong> 流程 <strong>异步化</strong>，减少系统 <strong>响应时间</strong>，提高 <strong>吞吐量</strong>。例如：<strong>短信通知</strong>、<strong>终端状态推送</strong>、<code>App</code> <strong>推送</strong>、<strong>用户注册</strong> 等。</p> <p><strong>消息队列</strong> 一般都内置了 <strong>高效的通信机制</strong>，因此也可以用于单纯的消息通讯，比如实现 <strong>点对点消息队列</strong> 或者 <strong>聊天室</strong> 等。</p> <h5 id="应用案例"><a href="#应用案例" class="header-anchor">#</a> 应用案例</h5> <p>网站用户注册，注册成功后会过一会发送邮件确认或者短息。</p> <p><img src="/assets/img/message-user-1.b0b13791.png" alt="img"></p> <h3 id="_5-2-系统解耦"><a href="#_5-2-系统解耦" class="header-anchor">#</a> 5.2. 系统解耦</h3> <ul><li>系统之间不是 <strong>强耦合的</strong>，<strong>消息接受者</strong> 可以随意增加，而不需要修改 <strong>消息发送者的代码</strong>。<strong>消息发送者</strong> 的成功不依赖 <strong>消息接受者</strong>（比如：有些银行接口不稳定，但调用方并不需要依赖这些接口）。</li> <li><strong>不强依赖</strong> 于非本系统的核心流程，对于 <strong>非核心流程</strong>，可以放到消息队列中让 <strong>消息消费者</strong> 去按需消费，而 <strong>不影响核心主流程</strong>。</li></ul> <h3 id="_5-3-最终一致性"><a href="#_5-3-最终一致性" class="header-anchor">#</a> 5.3. 最终一致性</h3> <p><strong>最终一致性</strong> 不是 <strong>消息队列</strong> 的必备特性，但确实可以依靠 <strong>消息队列</strong> 来做 <strong>最终一致性</strong> 的事情。</p> <ul><li><strong>先写消息再操作</strong>，确保操作完成后再修改消息状态。<strong>定时任务补偿机制</strong> 实现消息 <strong>可靠发送接收</strong>、业务操作的可靠执行，要注意 <strong>消息重复</strong> 与 <strong>幂等设计</strong>。</li> <li>所有不保证 <code>100%</code> <strong>不丢消息</strong> 的消息队列，理论上无法实现 <strong>最终一致性</strong>。</li></ul> <blockquote><p>像 <code>Kafka</code> 一类的设计，在设计层面上就有 <strong>丢消息</strong> 的可能（比如 <strong>定时刷盘</strong>，如果掉电就会丢消息）。哪怕只丢千分之一的消息，业务也必须用其他的手段来保证结果正确。</p></blockquote> <h3 id="_5-4-广播"><a href="#_5-4-广播" class="header-anchor">#</a> 5.4. 广播</h3> <p><strong>生产者/消费者</strong> 模式，只需要关心消息是否 <strong>送达队列</strong>，至于谁希望订阅和需要消费，是 <strong>下游</strong> 的事情，无疑极大地减少了开发和联调的工作量。</p> <p><img src="/assets/img/message-user-2.2e7aa769.png" alt="img"></p> <h3 id="_5-5-流量削峰和流控"><a href="#_5-5-流量削峰和流控" class="header-anchor">#</a> 5.5. 流量削峰和流控</h3> <p>当 <strong>上下游系统</strong> 处理能力存在差距的时候，利用 <strong>消息队列</strong> 做一个通用的 <strong>“漏斗”</strong>，进行 <strong>限流控制</strong>。在下游有能力处理的时候，再进行分发。</p> <blockquote><p>举个例子：用户在支付系统成功结账后，订单系统会通过短信系统向用户推送扣费通知。 <strong>短信系统</strong> 可能由于 <strong>短板效应</strong>，速度卡在 <strong>网关</strong> 上（每秒几百次请求），跟 <strong>前端的并发量</strong> 不是一个数量级。 于是，就造成 <strong>支付系统</strong> 和 <strong>短信系统</strong> 的处理能力出现差异化。</p></blockquote> <p>然而用户晚上个半分钟左右收到短信，一般是不会有太大问题的。如果没有消息队列，两个系统之间通过 <strong>协商</strong>、<strong>滑动窗口</strong> 等复杂的方案也不是说不能实现。但 <strong>系统复杂性</strong> 指数级增长，势必在 <strong>上游</strong> 或者 <strong>下游</strong> 做 <strong>存储</strong>，并且要处理 <strong>定时</strong>、<strong>拥塞</strong> 等一系列问题。而且每当有 <strong>处理能力有差距</strong> 的时候，都需要 <strong>单独</strong> 开发一套逻辑来维护这套逻辑。</p> <p>所以，利用中间系统转储两个系统的通信内容，并在下游系统有能力处理这些消息的时候，再处理这些消息，是一套相对较通用的方式。</p> <h4 id="应用案例-2"><a href="#应用案例-2" class="header-anchor">#</a> 应用案例</h4> <ol><li>把消息队列当成可靠的 <strong>消息暂存地</strong>，进行一定程度的 <strong>消息堆积</strong>；</li> <li>定时进行消息投递，比如模拟 <strong>用户秒杀</strong> 访问，进行 <strong>系统性能压测</strong>。</li></ol> <p><img src="/assets/img/message-user-3.12a995ff.png" alt="img"></p> <h3 id="_5-6-日志处理"><a href="#_5-6-日志处理" class="header-anchor">#</a> 5.6. 日志处理</h3> <p>将消息队列用在 <strong>日志处理</strong> 中，比如 <code>Kafka</code> 的应用，解决 <strong>海量日志</strong> 传输和缓冲的问题。</p> <h4 id="应用案例-3"><a href="#应用案例-3" class="header-anchor">#</a> 应用案例</h4> <p>把日志进行集中收集，用于计算 <code>PV</code>、<strong>用户行为分析</strong> 等等。</p> <p><img src="/assets/img/message-user-4.33666f59.png" alt="img"></p> <h3 id="_5-7-消息通讯"><a href="#_5-7-消息通讯" class="header-anchor">#</a> 5.7. 消息通讯</h3> <p>消息队列一般都内置了 <strong>高效的通信机制</strong>，因此也可以用于单纯的 <strong>消息通讯</strong>，比如实现 <strong>点对点消息队列</strong> 或者 <strong>聊天室</strong> 等。</p> <h2 id="_6-消息队列的推拉模型"><a href="#_6-消息队列的推拉模型" class="header-anchor">#</a> 6. 消息队列的推拉模型</h2> <h3 id="_6-1-push推消息模型"><a href="#_6-1-push推消息模型" class="header-anchor">#</a> 6.1. Push推消息模型</h3> <p><strong>消息生产者</strong> 将消息发送给 <strong>消息队列</strong>，<strong>消息队列</strong> 又将消息推给 <strong>消息消费者</strong>。</p> <h3 id="_6-2-pull拉消息模型"><a href="#_6-2-pull拉消息模型" class="header-anchor">#</a> 6.2. Pull拉消息模型</h3> <p><strong>消费者</strong> 请求 <strong>消息队列</strong> 接受消息，<strong>消息生产者</strong> 从 <strong>消息队列</strong> 中拉该消息。</p> <h3 id="_6-3-两种类型的区别"><a href="#_6-3-两种类型的区别" class="header-anchor">#</a> 6.3. 两种类型的区别</h3> <p><img src="/assets/img/message-push-pull.322304d7.png" alt="img"></p> <h2 id="_7-消息队列技术对比"><a href="#_7-消息队列技术对比" class="header-anchor">#</a> 7. 消息队列技术对比</h2> <p>本部分主要介绍四种常用的消息队列（<code>ActiveMQ</code> / <code>RabbitMQ</code> / <code>RocketMQ</code> / <code>Kafka</code>）的主要特性、优点、缺点。</p> <h3 id="_7-1-activemq"><a href="#_7-1-activemq" class="header-anchor">#</a> 7.1. ActiveMQ</h3> <p><code>ActiveMQ</code> 是由 <code>Apache</code> 出品，<code>ActiveMQ</code> 是一个完全支持<code>JMS1.1</code> 和 <code>J2EE 1.4</code> 规范的 <code>JMS Provider</code> 实现。它非常快速，支持 <strong>多种语言的客户端</strong> 和 <strong>协议</strong>，而且可以非常容易的嵌入到企业的应用环境中，并有许多高级功能。</p> <p><img src="/assets/img/message-acaticemq.93b836c1.png" alt="img"></p> <h4 id="a-主要特性"><a href="#a-主要特性" class="header-anchor">#</a> (a) 主要特性</h4> <ol><li><strong>服从JMS规范</strong>：<code>JMS</code> 规范提供了良好的标准和保证，包括：<strong>同步</strong> 或 <strong>异步</strong> 的消息分发，一次和仅一次的消息分发，<strong>消息接收</strong> 和 <strong>订阅</strong> 等等。遵从 <code>JMS</code> 规范的好处在于，不论使用什么 <code>JMS</code> 实现提供者，这些基础特性都是可用的；</li> <li><strong>连接灵活性</strong>：<code>ActiveMQ</code> 提供了广泛的 <strong>连接协议</strong>，支持的协议有：<code>HTTP/S</code>，<code>IP</code> <strong>多播</strong>，<code>SSL</code>，<code>TCP</code>，<code>UDP</code> 等等。对众多协议的支持让 <code>ActiveMQ</code> 拥有了很好的灵活性；</li> <li><strong>支持的协议种类多</strong>：<code>OpenWire</code>、<code>STOMP</code>、<code>REST</code>、<code>XMPP</code>、<code>AMQP</code>；</li> <li><strong>持久化插件和安全插件</strong>：<code>ActiveMQ</code> 提供了 <strong>多种持久化</strong> 选择。而且，<code>ActiveMQ</code> 的安全性也可以完全依据用户需求进行 <strong>自定义鉴权</strong> 和 <strong>授权</strong>；</li> <li><strong>支持的客户端语言种类多</strong>：除了 <code>Java</code> 之外，还有：<code>C/C++</code>，<code>.NET</code>，<code>Perl</code>，<code>PHP</code>，<code>Python</code>，<code>Ruby</code>；</li> <li><strong>代理集群</strong>：多个 <code>ActiveMQ</code> <strong>代理</strong> 可以组成一个 <strong>集群</strong> 来提供服务；</li> <li><strong>异常简单的管理</strong>：<code>ActiveMQ</code> 是以开发者思维被设计的。所以，它并不需要专门的管理员，因为它提供了简单又使用的管理特性。有很多中方法可以 <strong>监控</strong> <code>ActiveMQ</code> 不同层面的数据，包括使用在 <code>JConsole</code> 或者在 <code>ActiveMQ</code> 的 <code>Web Console</code> 中使用 <code>JMX</code>。通过处理 <code>JMX</code> 的告警消息，通过使用 <strong>命令行脚本</strong>，甚至可以通过监控各种类型的 <strong>日志</strong>。</li></ol> <h4 id="b-部署环境"><a href="#b-部署环境" class="header-anchor">#</a> (b) 部署环境</h4> <p><code>ActiveMQ</code> 可以运行在 <code>Java</code> 语言所支持的平台之上。使用 <code>ActiveMQ</code> 需要：</p> <ul><li><code>Java JDK</code></li> <li><code>ActiveMQ</code> 安装包</li></ul> <h4 id="c-优点"><a href="#c-优点" class="header-anchor">#</a> (c) 优点</h4> <ol><li><strong>跨平台</strong> (<code>JAVA</code> 编写与平台无关，<code>ActiveMQ</code> 几乎可以运行在任何的 <code>JVM</code> 上)；</li> <li>可以用 <code>JDBC</code>：可以将 <strong>数据持久化</strong> 到数据库。虽然使用 <code>JDBC</code> 会降低 <code>ActiveMQ</code> 的性能，但是数据库一直都是开发人员最熟悉的存储介质；</li> <li>支持 <code>JMS</code> 规范：支持 <code>JMS</code> 规范提供的 <strong>统一接口</strong>;</li> <li>支持 <strong>自动重连</strong> 和 <strong>错误重试机制</strong>；</li> <li>有安全机制：支持基于 <code>shiro</code>，<code>jaas</code> 等多种 <strong>安全配置机制</strong>，可以对 <code>Queue/Topic</code> 进行 <strong>认证和授权</strong>；</li> <li>监控完善：拥有完善的 <strong>监控</strong>，包括 <code>Web Console</code>，<code>JMX</code>，<code>Shell</code> 命令行，<code>Jolokia</code> 的 <code>RESTful API</code>；</li> <li>界面友善：提供的 <code>Web Console</code> 可以满足大部分情况，还有很多 <strong>第三方的组件</strong> 可以使用，比如 <code>hawtio</code>；</li></ol> <h4 id="d-缺点"><a href="#d-缺点" class="header-anchor">#</a> (d) 缺点</h4> <ol><li>社区活跃度不及 <code>RabbitMQ</code> 高；</li> <li>根据其他用户反馈，会出莫名其妙的问题，会 <strong>丢失消息</strong>；</li> <li>目前重心放到 <code>activemq 6.0</code> 产品 <code>Apollo</code>，对 <code>5.x</code> 的维护较少；</li> <li>不适合用于 <strong>上千个队列</strong> 的应用场景；</li></ol> <h3 id="_7-2-rabbitmq"><a href="#_7-2-rabbitmq" class="header-anchor">#</a> 7.2. RabbitMQ</h3> <p><code>RabbitMQ</code> 于 <code>2007</code> 年发布，是一个在 <code>AMQP</code> (<strong>高级消息队列协议</strong>)基础上完成的，可复用的企业消息系统，是当前最主流的消息中间件之一。</p> <p><img src="/assets/img/message-rabbitmq.f0a81bc0.png" alt="img"></p> <h4 id="a-主要特性-2"><a href="#a-主要特性-2" class="header-anchor">#</a> (a) 主要特性</h4> <ol><li><strong>可靠性</strong>：提供了多种技术可以让你在 <strong>性能</strong> 和 <strong>可靠性</strong> 之间进行 <strong>权衡</strong>。这些技术包括 <strong>持久性机制</strong>、<strong>投递确认</strong>、<strong>发布者证实</strong> 和 <strong>高可用性机制</strong>；</li> <li><strong>灵活的路由</strong>：消息在到达队列前是通过 <strong>交换机</strong> 进行 <strong>路由</strong> 的。<code>RabbitMQ</code> 为典型的路由逻辑提供了 <strong>多种内置交换机</strong> 类型。如果你有更复杂的路由需求，可以将这些交换机组合起来使用，你甚至可以实现自己的交换机类型，并且当做 <code>RabbitMQ</code> 的 <strong>插件</strong> 来使用；</li> <li><strong>消息集群</strong>：在相同局域网中的多个 <code>RabbitMQ</code> 服务器可以 <strong>聚合</strong> 在一起，作为一个独立的逻辑代理来使用；</li> <li><strong>队列高可用</strong>：队列可以在集群中的机器上 <strong>进行镜像</strong>，以确保在硬件问题下还保证 <strong>消息安全</strong>；</li> <li><strong>支持多种协议</strong>：支持 <strong>多种消息队列协议</strong>；</li> <li><strong>支持多种语言</strong>：用 <code>Erlang</code> 语言编写，支持只要是你能想到的 <strong>所有编程语言</strong>；</li> <li><strong>管理界面</strong>： <code>RabbitMQ</code> 有一个易用的 <strong>用户界面</strong>，使得用户可以 <strong>监控</strong> 和 <strong>管理</strong> 消息 <code>Broker</code> 的许多方面；</li> <li><strong>跟踪机制</strong>：如果 <strong>消息异常</strong>，<code>RabbitMQ</code> 提供消息跟踪机制，使用者可以找出发生了什么；</li> <li><strong>插件机制</strong>：提供了许多 <strong>插件</strong>，来从多方面进行扩展，也可以编写自己的插件。</li></ol> <h4 id="b-部署环境-2"><a href="#b-部署环境-2" class="header-anchor">#</a> (b) 部署环境</h4> <p><code>RabbitMQ</code> 可以运行在 <code>Erlang</code> 语言所支持的平台之上，包括 <code>Solaris</code>，<code>BSD</code>，<code>Linux</code>，<code>MacOSX</code>，<code>TRU64</code>，<code>Windows</code> 等。使用 <code>RabbitMQ</code> 需要：</p> <ul><li><code>ErLang</code> 语言包</li> <li><code>RabbitMQ</code> 安装包</li></ul> <h4 id="c-优点-2"><a href="#c-优点-2" class="header-anchor">#</a> (c) 优点</h4> <ol><li>由于 <code>Erlang</code> 语言的特性，消息队列性能较好，支持 <strong>高并发</strong>；</li> <li>健壮、稳定、易用、<strong>跨平台</strong>、支持 <strong>多种语言</strong>、文档齐全；</li> <li>有消息 <strong>确认机制</strong> 和 <strong>持久化机制</strong>，可靠性高；</li> <li>高度可定制的 <strong>路由</strong>；</li> <li><strong>管理界面</strong> 较丰富，在互联网公司也有较大规模的应用，社区活跃度高。</li></ol> <h4 id="d-缺点-2"><a href="#d-缺点-2" class="header-anchor">#</a> (d) 缺点</h4> <ol><li>尽管结合 <code>Erlang</code> 语言本身的并发优势，性能较好，但是不利于做 <strong>二次开发和维护</strong>；</li> <li>实现了 <strong>代理架构</strong>，意味着消息在发送到客户端之前可以在 <strong>中央节点</strong> 上排队。此特性使得 <code>RabbitMQ</code> 易于使用和部署，但是使得其 <strong>运行速度较慢</strong>，因为中央节点 <strong>增加了延迟</strong>，<strong>消息封装后</strong> 也比较大；</li> <li>需要学习 <strong>比较复杂</strong> 的 <strong>接口和协议</strong>，学习和维护成本较高。</li></ol> <h3 id="_7-3-rocketmq"><a href="#_7-3-rocketmq" class="header-anchor">#</a> 7.3. RocketMQ</h3> <p><code>RocketMQ</code> 出自 <strong>阿里</strong> 的开源产品，用 <code>Java</code> 语言实现，在设计时参考了 <code>Kafka</code>，并做出了自己的一些改进，<strong>消息可靠性上</strong> 比 <code>Kafka</code> 更好。<code>RocketMQ</code> 在阿里内部被广泛应用在 <strong>订单</strong>，<strong>交易</strong>，<strong>充值</strong>，<strong>流计算</strong>，<strong>消息推送</strong>，<strong>日志流式处理</strong>，<code>binglog</code> <strong>分发</strong> 等场景。</p> <h4 id="a-主要特性-3"><a href="#a-主要特性-3" class="header-anchor">#</a> (a) 主要特性</h4> <p><img src="/assets/img/message-rocketmq.882d02f5.png" alt="img"></p> <ol><li>基于 <strong>队列模型</strong>：具有 <strong>高性能</strong>、<strong>高可靠</strong>、<strong>高实时</strong>、<strong>分布式</strong> 等特点；</li> <li><code>Producer</code>、<code>Consumer</code>、<strong>队列</strong> 都支持 <strong>分布式</strong>；</li> <li><code>Producer</code> 向一些队列轮流发送消息，<strong>队列集合</strong> 称为 <code>Topic</code>。<code>Consumer</code> 如果做 <strong>广播消费</strong>，则一个 <code>Consumer</code> 实例消费这个 <code>Topic</code> 对应的 <strong>所有队列</strong>；如果做 <strong>集群消费</strong>，则 <strong>多个</strong> <code>Consumer</code> 实例 <strong>平均消费</strong> 这个 <code>Topic</code> 对应的队列集合；</li> <li>能够保证 <strong>严格的消息顺序</strong>；</li> <li>提供丰富的 <strong>消息拉取模式</strong>；</li> <li>高效的订阅者 <strong>水平扩展</strong>能力；</li> <li><strong>实时</strong> 的 <strong>消息订阅机制</strong>；</li> <li>亿级 <strong>消息堆积</strong> 能力；</li> <li>较少的外部依赖。</li></ol> <h4 id="b-部署环境-3"><a href="#b-部署环境-3" class="header-anchor">#</a> (b) 部署环境</h4> <p><code>RocketMQ</code> 可以运行在 <code>Java</code> 语言所支持的平台之上。使用 <code>RocketMQ</code> 需要：</p> <ul><li><code>Java JDK</code></li> <li>安装 <code>git</code>、<code>Maven</code></li> <li><code>RocketMQ</code> 安装包</li></ul> <h4 id="c-优点-3"><a href="#c-优点-3" class="header-anchor">#</a> (c) 优点</h4> <ol><li><strong>单机</strong> 支持 <code>1</code> 万以上 <strong>持久化队列</strong>；</li> <li><code>RocketMQ</code> 的所有消息都是 <strong>持久化的</strong>，先写入系统  <code>PAGECACHE</code>，然后 <strong>刷盘</strong>，可以保证 <strong>内存</strong> 与 <strong>磁盘</strong> 都有一份数据，而 <strong>访问</strong> 时，直接 <strong>从内存读取</strong>。</li> <li>模型简单，接口易用（<code>JMS</code> 的接口很多场合并不太实用）；</li> <li><strong>性能非常好</strong>，可以允许 <strong>大量堆积消息</strong> 在 <code>Broker</code> 中；</li> <li>支持 <strong>多种消费模式</strong>，包括 <strong>集群消费</strong>、<strong>广播消费</strong>等；</li> <li>各个环节 <strong>分布式扩展设计</strong>，支持 <strong>主从</strong> 和 <strong>高可用</strong>；</li> <li>开发度较活跃，版本更新很快。</li></ol> <h4 id="d-缺点-3"><a href="#d-缺点-3" class="header-anchor">#</a> (d) 缺点</h4> <ol><li>支持的 <strong>客户端语言</strong> 不多，目前是 <code>Java</code> 及 <code>C++</code>，其中 <code>C++</code> 还不成熟；</li> <li><code>RocketMQ</code> 社区关注度及成熟度也不及前两者；</li> <li>没有 <code>Web</code> 管理界面，提供了一个 <code>CLI</code> (命令行界面) 管理工具带来 <strong>查询</strong>、<strong>管理</strong> 和 <strong>诊断各种问题</strong>；</li> <li>没有在 <code>MQ</code> 核心里实现 <code>JMS</code> 等接口；</li></ol> <h3 id="_7-4-kafka"><a href="#_7-4-kafka" class="header-anchor">#</a> 7.4. Kafka</h3> <p><code>Apache Kafka</code> 是一个 <strong>分布式消息发布订阅</strong> 系统。它最初由 <code>LinkedIn</code> 公司基于独特的设计实现为一个 <strong>分布式的日志提交系统</strong> (<code>a distributed commit log</code>)，之后成为 <code>Apache</code> 项目的一部分。<code>Kafka</code> <strong>性能高效</strong>、<strong>可扩展良好</strong> 并且 <strong>可持久化</strong>。它的 <strong>分区特性</strong>，<strong>可复制</strong> 和 <strong>可容错</strong> 都是其不错的特性。</p> <p><img src="/assets/img/message-kafka.d09b259a.png" alt="img"></p> <h4 id="a-主要特性-4"><a href="#a-主要特性-4" class="header-anchor">#</a> (a) 主要特性</h4> <ol><li><strong>快速持久化</strong>：可以在 <code>O(1)</code> 的系统开销下进行 <strong>消息持久化</strong>；</li> <li><strong>高吞吐</strong>：在一台普通的服务器上既可以达到 <code>10W/s</code> 的 <strong>吞吐速率</strong>；</li> <li><strong>完全的分布式系统</strong>：<code>Broker</code>、<code>Producer</code> 和 <code>Consumer</code> 都原生自动支持 <strong>分布式</strong>，自动实现 <strong>负载均衡</strong>；</li> <li>支持 <strong>同步</strong> 和 <strong>异步</strong> 复制两种 <strong>高可用机制</strong>；</li> <li>支持 <strong>数据批量发送</strong> 和 <strong>拉取</strong>；</li> <li><strong>零拷贝技术(zero-copy)</strong>：减少 <code>IO</code> 操作步骤，提高 <strong>系统吞吐量</strong>；</li> <li><strong>数据迁移</strong>、<strong>扩容</strong> 对用户透明；</li> <li><strong>无需停机</strong> 即可扩展机器；</li> <li><strong>其他特性</strong>：丰富的 <strong>消息拉取模型</strong>、高效 <strong>订阅者水平扩展</strong>、实时的 <strong>消息订阅</strong>、亿级的 <strong>消息堆积能力</strong>、定期删除机制；</li></ol> <h4 id="b-部署环境-4"><a href="#b-部署环境-4" class="header-anchor">#</a> (b) 部署环境</h4> <p>使用 <code>Kafka</code> 需要：</p> <ul><li><code>Java JDK</code></li> <li><code>Kafka</code> 安装包</li></ul> <h4 id="c-优点-4"><a href="#c-优点-4" class="header-anchor">#</a> (c) 优点</h4> <ol><li><strong>客户端语言丰富</strong>：支持 <code>Java</code>、<code>.Net</code>、<code>PHP</code>、<code>Ruby</code>、<code>Python</code>、<code>Go</code> 等多种语言；</li> <li><strong>高性能</strong>：单机写入 <code>TPS</code> 约在 <code>100</code> 万条/秒，消息大小 <code>10</code> 个字节；</li> <li>提供 <strong>完全分布式架构</strong>，并有 <code>replica</code> 机制，拥有较高的 <strong>可用性</strong> 和 <strong>可靠性</strong>，理论上支持 <strong>消息无限堆积</strong>；</li> <li>支持批量操作；</li> <li><strong>消费者</strong> 采用 <code>Pull</code> 方式获取消息。<strong>消息有序</strong>，<strong>通过控制</strong> 能够保证所有消息被消费且仅被消费 <strong>一次</strong>；</li> <li>有优秀的第三方 <code>Kafka Web</code> 管理界面 <code>Kafka-Manager</code>；</li> <li>在 <strong>日志领域</strong> 比较成熟，被多家公司和多个开源项目使用。</li></ol> <h4 id="d-缺点-4"><a href="#d-缺点-4" class="header-anchor">#</a> (d) 缺点</h4> <ol><li><code>Kafka</code> 单机超过 <code>64</code> 个 <strong>队列/分区</strong> 时，<code>Load</code> 时会发生明显的飙高现象。<strong>队列</strong> 越多，<strong>负载</strong> 越高，发送消息 <strong>响应时间变长</strong>；</li> <li>使用 <strong>短轮询方式</strong>，<strong>实时性</strong> 取决于 <strong>轮询间隔时间</strong>；</li> <li>消费失败 <strong>不支持重试</strong>；</li> <li>支持 <strong>消息顺序</strong>，但是 <strong>一台代理宕机</strong> 后，就会产生 <strong>消息乱序</strong>；</li> <li>社区更新较慢。</li></ol> <h3 id="_7-5-几种消息队列对比"><a href="#_7-5-几种消息队列对比" class="header-anchor">#</a> 7.5. 几种消息队列对比</h3> <p>这里列举了上述四种消息队列的差异对比：</p> <table><thead><tr><th></th> <th>RabbitMQ</th> <th>ActiveMQ</th> <th>RocketMQ</th> <th>Kafka</th></tr></thead> <tbody><tr><td>所属社区/公司</td> <td>Rabbit</td> <td>Apache</td> <td>Ali</td> <td>Apache</td></tr> <tr><td>开发语言</td> <td>Erlang</td> <td>Java</td> <td>Java</td> <td>Scala&amp;Java</td></tr> <tr><td>多语言支持</td> <td>语言无关</td> <td>支持，Java优先</td> <td>Java</td> <td>支持，Java优先</td></tr> <tr><td>消息推拉模式</td> <td>多协议，Pull/Push均支持</td> <td>多协议，Pull/Push均支持</td> <td>多协议，Pull/Push均支持</td> <td>Pull</td></tr> <tr><td>HA</td> <td>master/slave模式，master提供服务，slave仅作备份</td> <td>基于zookeeper+levelDB的master-slave实现方式</td> <td>支持多master模式、多master多slave模式、异步复制模式、</td> <td>支持replica机制。leader宕掉后，备份自动顶替，并重选leader</td></tr> <tr><td>事务</td> <td>不支持</td> <td>支持</td> <td>支持</td> <td>不支持，可通过Low Level API保证仅消费一次</td></tr> <tr><td>集群</td> <td>支持</td> <td>支持</td> <td>支持</td> <td>支持</td></tr> <tr><td>负载均衡</td> <td>支持</td> <td>支持</td> <td>支持</td> <td>支持</td></tr></tbody></table> <p><code>Kafka</code> 在于 <strong>分布式架构</strong>，<code>RabbitMQ</code> 基于 <code>AMQP</code> <strong>协议</strong> 来实现，<code>RocketMQ</code> 的思路来源于 <code>Kafka</code>，改成了 <strong>主从结构</strong>，在 <strong>事务性</strong> 和 <strong>可靠性</strong> 方面做了优化。广泛来说，<strong>电商</strong>、<strong>金融</strong> 等对 <strong>事务一致性</strong> 要求很高的，可以考虑 <code>RabbitMQ</code> 和 <code>RocketMQ</code>，对 <strong>性能要求高</strong> 的可考虑 <code>Kafka</code>。</p> <h2 id="参考与感谢"><a href="#参考与感谢" class="header-anchor">#</a> 参考与感谢</h2> <p>https://juejin.im/post/5b41fe36e51d45191252e79e#heading-2</p></div> <footer class="page-edit" style="display:none;"><!----> <!----></footer> <!----> <!----> <!----></main> <!----></div></div></div></div><div class="global-ui"><div class="back-to-ceiling" style="right:1rem;bottom:6rem;width:2.5rem;height:2.5rem;border-radius:.25rem;line-height:2.5rem;display:none;" data-v-db14854a data-v-db14854a><svg t="1574745035067" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5404" class="icon" data-v-db14854a><path d="M526.60727968 10.90185116a27.675 27.675 0 0 0-29.21455937 0c-131.36607665 82.28402758-218.69155461 228.01873535-218.69155402 394.07834331a462.20625001 462.20625001 0 0 0 5.36959153 69.94390903c1.00431239 6.55289093-0.34802892 13.13561351-3.76865779 18.80351572-32.63518765 54.11355614-51.75690182 118.55860487-51.7569018 187.94566865a371.06718723 371.06718723 0 0 0 11.50484808 91.98906777c6.53300375 25.50556257 41.68394495 28.14064038 52.69160883 4.22606766 17.37162448-37.73630017 42.14135425-72.50938081 72.80769204-103.21549295 2.18761121 3.04276886 4.15646224 6.24463696 6.40373557 9.22774369a1871.4375 1871.4375 0 0 0 140.04691725 5.34970492 1866.36093723 1866.36093723 0 0 0 140.04691723-5.34970492c2.24727335-2.98310674 4.21612437-6.18497483 6.3937923-9.2178004 30.66633723 30.70611158 55.4360664 65.4791928 72.80769147 103.21549355 11.00766384 23.91457269 46.15860503 21.27949489 52.69160879-4.22606768a371.15156223 371.15156223 0 0 0 11.514792-91.99901164c0-69.36717486-19.13165746-133.82216804-51.75690182-187.92578088-3.42062944-5.66790279-4.76302748-12.26056868-3.76865837-18.80351632a462.20625001 462.20625001 0 0 0 5.36959269-69.943909c-0.00994388-166.08943902-87.32547796-311.81420293-218.6915546-394.09823051zM605.93803103 357.87693858a93.93749974 93.93749974 0 1 1-187.89594924 6.1e-7 93.93749974 93.93749974 0 0 1 187.89594924-6.1e-7z" p-id="5405" data-v-db14854a></path><path d="M429.50777625 765.63860547C429.50777625 803.39355007 466.44236686 1000.39046097 512.00932183 1000.39046097c45.56695499 0 82.4922232-197.00623328 82.5015456-234.7518555 0-37.75494459-36.9345906-68.35043303-82.4922232-68.34111062-45.57627738-0.00932239-82.52019037 30.59548842-82.51086798 68.34111062z" p-id="5406" data-v-db14854a></path></svg></div><!----></div></div>
    <script src="/assets/js/app.447d4224.js" defer></script><script src="/assets/js/3.9d76740c.js" defer></script><script src="/assets/js/1.c4fd7d2e.js" defer></script><script src="/assets/js/7.6609d4d6.js" defer></script>
  </body>
</html>
